﻿// <copyright file="EslException.cs" company="Codeplex project Eco.Contrib"> 
// The MIT License (MIT) 
// </copyright> 
// <author>Peter Buchmann</author> 

namespace Eco.Contrib
{
    using System;
    using System.Runtime.Serialization;
    using System.Security.Permissions;

    /// <summary>
    /// Exception, thrown by ESLService
    /// </summary>
    [Serializable]
    public class EslException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        public EslException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        public EslException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public EslException(string message, Exception exception)
            : base(message, exception)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="line">The line.</param>
        /// <param name="col">The col.</param>
        /// <param name="pos">The pos.</param>
        /// <param name="innerException">The inner exception.</param>
        public EslException(string message, int line, int col, int pos, Exception innerException)
            : base(message, innerException)
        {
            this.Line = line;
            this.Col = col;
            this.Pos = pos;

            while (innerException != null)
            {
                EslException eslException = innerException as EslException;
                if (eslException != null)
                {
                    this.Line = eslException.Line;
                    this.Col = eslException.Col;
                    this.Pos = eslException.Pos;
                    break;
                }

                innerException = innerException.InnerException;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="token">The token.</param>
        public EslException(string message, EslToken token)
            : base(message)
        {
            if (token != null)
            {
                this.Line = token.Line;
                this.Col = token.Col;
                this.Pos = token.Pos;
            }
            else
            {
                this.Line = 0;
                this.Col = 0;
                this.Pos = 0;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EslException"/> class.
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
        protected EslException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        /// <summary>
        /// Gets the line.
        /// </summary>
        public int Line { get; private set; }

        /// <summary>
        /// Gets the col.
        /// </summary>
        public int Col { get; private set; }

        /// <summary>
        /// Gets the pos.
        /// </summary>
        public int Pos { get; private set; }

        /// <summary>
        /// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with information about the exception.
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is a null reference (Nothing in Visual Basic). </exception>
        /// <PermissionSet>
        ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*"/>
        ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter"/>
        /// </PermissionSet>
        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }

            info.AddValue("Line", this.Line);
            info.AddValue("Col", this.Col);
            info.AddValue("Pos", this.Pos);
            base.GetObjectData(info, context);
        }
    }
}
